package visitor;

import hypeerweb.Node;
import hypeerweb.WebId;
import java.util.ArrayList;

public abstract class BroadcastVisitor implements Visitor {
	
	private static final long serialVersionUID = 1L;
	protected static final String STARTED_KEY = "";
    protected static final WebId NODE_0_ID = new WebId(0);
    
	public static Parameters params;
	
	/**
	 * Default Constructor.
	 */
	public BroadcastVisitor(){

	}
	
	/**
	 * Visits the node that is passed in and decides it's next course of action.
	 * 
	 *  @param node
	 *  		the node that is being visited by the visitor
	 *  @param parameters
	 *  		the parameters for the visitor pertaining to its desired goal
	 *  @pre none
	 *  
	 *  @post if the node is to be visited, it will be the post condition of operation(node, parameters)
	 */
	public void visit(Node node, Parameters parameters) {
        if (parameters.containsKey(STARTED_KEY)) {
//        	System.out.println("Broadcasting and we hit node #" + node.getWebId().getValue());
            operation(node, parameters);
            broadcastToNeighbors(node, parameters);
        }
        else {
//        	System.out.println("we have to find node0 " + node.getWebId().getValue());
            parameters.set(STARTED_KEY, "");
            Node node0 = node.find(node, NODE_0_ID);
            if(node0 != null) {
            	System.out.println("Node0 is " + node0.getWebId().getValue() + " " + node0.getConnections());
            	node0.accept(this, parameters);
            }
        }
	}

	/**
	 * Creates the parameters for the visitor.
	 * 
	 * @return the default parameters for this visitor
	 * 
	 */
	public static Parameters createInitialParameters() {
		params = new Parameters();
		return params;
	}
	
	/**
	 * 
	 * 
	 * @param node
	 * 			the node on which to perform the operation on
	 * @param parameters
	 * 			The parameters holding what the operation should be doing.
	 * @pre none
	 * 
	 * @post node has had the operation performed on it.
	 * 
	 * 
	 */	
	protected abstract void operation(Node node, Parameters parameters);

    private void broadcastToNeighbors(Node node, Parameters parameters) {
        ArrayList<Node> neighborsForBroadcast = node.getNeighborsToBroadcast();
        for (Node broadcastNeighbor : neighborsForBroadcast) {
            broadcastNeighbor.accept(this, parameters);
        }
    }
}
